package com.boot.AutoFillAnnotation;

import com.boot.interceptor.BaseContext;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Slf4j
@Component
@Aspect
public class AutoFillAspect {
    //定义范围，扫描哪些方法，并且包含自定义注解的
    @Pointcut("execution(* com.boot.controller.EmployeeController.*(..)) && @annotation(com.boot.AutoFillAnnotation.AutoFill)")
    public void autoFillPointCut() {
    }

    //定义前置切面
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint) {
        //获取方法标记，MethodSignature是Signature的向下转型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        //获取方法上的注解和注解标记的类型
        AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);
        OperationType operationType = annotation.value();

        //获取参数
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;
        }

        //第一个参数，对象实例
        Object entity = args[0];

        LocalDateTime createTime = LocalDateTime.now();
        LocalDateTime updateTime = LocalDateTime.now();
        //这儿需要再登录的时候就存一个id，这儿才能取到
        Long userId = BaseContext.getCurrentId();


        //以insert为例，需要更新的东西
        if (operationType == OperationType.INSERT) {
            try {
                //获取各个方法对象
                Method setCreateTime = entity.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
                Method setCreateUser = entity.getClass().getDeclaredMethod("setCreateUser", Long.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);
                setCreateTime.setAccessible(true);
                setUpdateTime.setAccessible(true);
                setCreateUser.setAccessible(true);
                setUpdateUser.setAccessible(true);
                setCreateTime.invoke(entity, createTime);
                setUpdateTime.invoke(entity, updateTime);
                setCreateUser.invoke(entity, userId);
                setUpdateUser.invoke(entity, userId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
